<template>
  <mu-v-box
    :class="`mu-modal-mask${ params.noMask ? ' no-mask' : '' }`"
    flex-center
    :visible="params.modalVisible"
    @click.native="onMaskClick">
    <mu-v-box
      v-if="params.keepAlive || params.modalVisible"
      v-show="!params.keepAlive || params.modalVisible"
      class="mu-dialog"
      :style="style"
      :danger="params.danger"
      :visible="params.dialogVisible"
      @mousemove.native="onMousemove"
      @mousedown.native="onMousedown">
      <mu-h-box
        class="mu-dialog-header"
        align-items="center">
        <mu-flex-item class="mu-dialog-title mu-text-ellipsis" size="auto">
          {{ params.title }}
        </mu-flex-item>
        <slot name="header" />
        <mu-icon
          icon-class="ipm-iconclose"
          class="mu-text-color-subtitle clickable"
          @click="hide('$close')" />
      </mu-h-box>
      <mu-flex-item
        class="mu-dialog-body"
        :style="params.bodyWidth? 'width:'+params.bodyWidth : undefined"
        :size="params.height ? 'auto' : params.bodyHeight ? params.bodyHeight :undefined">
        <slot />
      </mu-flex-item>
      <mu-h-box
        v-if="params.footer"
        class="mu-dialog-footer"
        align-items="center">
        <slot name="footer" />
        <div style="margin-right: auto" />
        <mu-button
          v-for="btn in params.buttons"
          :key="btn.caption || btn.icon || btn.iconClass"
          v-bind="btn"
          @click="onButtonClick(btn)" />
      </mu-h-box>
    </mu-v-box>
  </mu-v-box>
</template>

<script>
  import getClientRect from './client-rect'

  export default {
    name: 'MusselDialogWrapper',
    inject: ['dialog', 'params'],
    data () {
      return {
        translateX: 0,
        translateY: 0,
        transitionDuration: '.2s',
        telescopicDirection: '',
        startScalable: false,
        clientX: 0,
        clientY: 0
      }
    },
    computed: {
      style () {
        const { dialogVisible: visible, width, height } = this.params
        let {
          translateX: tx,
          translateY: ty,
          transitionDuration
        } = this
        ty = visible ? ty : ty + 200
        return {
          width,
          height,
          transitionDuration,
          transform: `translate3d(${tx}px, ${ty}px, 0)`
        }
      }
    },
    methods: {
      onMaskClick (event) {
        if (!this.dragState) this.dialog.onMaskClick(event)
      },
      hide (btn) {
        this.dialog.hide(false, btn)
      },
      onButtonClick (btn) {
        this.dialog.onButtonClick(btn)
      },

      // 获取鼠标所在div的位置
      getDirection (event, container) {
        let dir = ''
        const xP = event.offsetX
        const yP = event.clientY - container.getBoundingClientRect().top
        const offset = 4
        if (yP < offset) dir += 'n'
        else if (yP > container.offsetHeight - offset) dir += 's'
        if (xP < offset) dir += 'w'
        else if (xP > container.offsetWidth - offset) dir += 'e'
        return dir
      },

      onMousemove (event) {
        const container = this.$el.querySelector('.mu-dialog')
        const { target } = event
        const isIcon = String(target.className).indexOf('mu-icon') !== -1
        const isInput = target.tagName.toLowerCase() === 'input'
        if (!container || this.params.scalable === false || isIcon || isInput) return

        const dir = this.getDirection(event, container)
        if (dir) { // 可移动
          container.style.cursor = dir + '-resize'
        } else { // 可拖动
          container.style.cursor = 'default'
        }
        if (!this.startScalable) {
          this.telescopicDirection = dir
        }
      },

      onMouseup () {
        this.startScalable = false
        this.telescopicDirection = ''
        window.removeEventListener('mouseup', this.onMouseup)
      },

      // 处理伸缩
      openScalable (event) {
        if (!this.startScalable) {
          window.removeEventListener('mousemove', this.openScalable)
          return
        }

        window.addEventListener('mouseup', this.onMouseup)
        const container = this.$el.querySelector('.mu-dialog-body')

        const { height, width } = getClientRect(container)

        const minW = 200
        const minH = 0

        // 鼠标按下的位置在右边，修改宽度
        if (this.telescopicDirection.indexOf('e') !== -1) {
          container.style.width = Math.max(minW, width + (event.clientX - this.clientX)) + 'px'
          this.clientX = event.clientX
        }

        // 鼠标按下的位置在上部，修改高度
        if (this.telescopicDirection.indexOf('n') !== -1) {
          container.style.height = Math.max(minH, height + (this.clientY - event.clientY)) + 'px'
          this.clientY = event.clientY
        }

        // 鼠标按下的位置在底部，修改高度
        if (this.telescopicDirection.indexOf('s') !== -1) {
          container.style.height = Math.max(minH, height + (event.clientY - this.clientY)) + 'px'
          this.clientY = event.clientY
        }

        // // 鼠标按下的位置在左边，修改宽度
        if (this.telescopicDirection.indexOf('w') !== -1) {
          container.style.width = Math.max(minW, width + (this.clientX - event.clientX)) + 'px'
          this.clientX = event.clientX
        }

        this.$emit('resize', { height, width })
      },

      // 按下去
      onMousedown (event) {
        const container = this.$el.querySelector('.mu-dialog')
        if (this.telescopicDirection) { // 可移动
          container.style.cursor = this.telescopicDirection + '-resize'
          this.startScalable = true
          this.clientX = event.clientX
          this.clientY = event.clientY
          window.addEventListener('mousemove', this.openScalable)
        } else { // 可拖动
          container.style.cursor = 'default'
          const header = this.$el.querySelector('.mu-dialog-header')
          const {
            bottom,
            left,
            right,
            top
          } = getClientRect(header)
          const xInHead = event.clientX < right && event.clientX > left
          const yInHead = event.clientY < bottom && event.clientY > top
          if (xInHead && yInHead) {
            this.onDragStart(event)
          }
        }
      },

      onDragStart (event) {
        const { target, pageX, pageY } = event
        const el = this.$el.querySelector('.mu-dialog')
        const isIcon = String(target.className).indexOf('mu-icon') !== -1
        const isInput = target.tagName.toLowerCase() === 'input'

        if (!el || this.params.draggable === false || isIcon || isInput) return

        this.dragState = {
          tx: this.translateX,
          ty: this.translateY,
          startX: pageX,
          startY: pageY,
          el: this.$el.querySelector('.mu-dialog')
        }
        this.$el.querySelector('.mu-dialog').style.cursor = 'grab'
        this.transitionDuration = '0s'
        window.addEventListener('mousemove', this.onDragMove)
        window.addEventListener('mouseup', this.onDragEnd)
      },

      onDragMove (event) {
        if (!this.dragState) return

        const { pageX: x, pageY: y } = event
        const { el, tx, ty, startX, startY } = this.dragState
        const { top, left } = getClientRect(el)
        const newX = tx + x - startX
        const newY = ty + y - startY
        if (
          (left > 0 || newX > this.translateX) &&
          (x < window.innerWidth)
        ) {
          this.translateX = newX
        }
        if (
          (top > 0 || ty + y - startY > this.translateY) &&
          (y < window.innerHeight)
        ) {
          this.translateY = newY
        }
      },

      onDragEnd (event) {
        if (!this.dragState) return
        window.removeEventListener('mousemove', this.onDragMove)
        window.removeEventListener('mouseup', this.onDragEnd)
        this.$el.querySelector('.mu-dialog').style.cursor = 'default'
        this.transitionDuration = '.2s'
        setTimeout(() => {
          delete this.dragState
        }, 50)
      }
    }
  }
</script>
<style scoped>
  .no-mask {
    background-color: transparent !important;
  }
  .clickable:hover {
    cursor: pointer;
  }
</style>
